
//这部分代码负责在屏幕上显示东西
#include <disp_manager.h>
#include <stdio.h>
#include <string.h>
//这部分代码起承上启下的作用，管理底层的LCD WEB
static PDispOpr g_DispDevs = NULL; //设置一个链表，将他们管理起来
static PDispOpr g_DispDefault = NULL; //使用NULL要包含头文件，或者自己定义，代码是自己定义的
static DispBuff g_tDispBuff;
static int line_width;
static int pixel_width;

//8、写程序16的时候加的，font_test.c中的   /* draw on buffer 绘图 */，宝库中的10-04
void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)
{
    int i, j, p, q;
	int x = ptFontBitMap->tRegion.iLeftUpX;
	int y = ptFontBitMap->tRegion.iLeftUpY;
    int x_max = x + ptFontBitMap->tRegion.iWidth;
    int y_max = y + ptFontBitMap->tRegion.iHeigh;
	int width = ptFontBitMap->tRegion.iWidth;
	unsigned char *buffer = ptFontBitMap->pucBuffer;

    //printf("x = %d, y = %d\n", x, y);

    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
        for ( i = x, p = 0; i < x_max; i++, p++ )
        {
            if ( i < 0      || j < 0       ||
                i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres )
            continue;

            //image[j][i] |= bitmap->buffer[q * bitmap->width + p];
            if (buffer[q * width + p]) //？？？？
	            PutPixel(i, j, dwColor);
        }
    }
}

//9、绘制按钮区域ptRegion左边信息
void DrawRegion(PRegion ptRegion, unsigned int dwColor)
{
	int x = ptRegion->iLeftUpX;
	int y = ptRegion->iLeftUpY;
	int width = ptRegion->iWidth;
	int heigh = ptRegion->iHeigh;

	int i,j;

	for (j = y; j < y + heigh; j++)
	{
		for (i = x; i < x + width; i++)
			PutPixel(i, j, dwColor);
	}
}
//10、绘制按钮区域中的文字，课中讲了画图原理（8-1）
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor)
{
	FontBitMap tFontBitMap;//区分位图和region
	RegionCartesian tRegionCar;

	int iOriginX, iOriginY;
	int i = 0;
	int error;

	/* 计算字符串的外框 */
	GetStringRegionCar(name, &tRegionCar);
	
	//算出第一个字符的origin（原点）
	iOriginX = (ptRegion->iWidth - n * iFontSize)/2 + ptRegion->iLeftUpX;
	iOriginY = (ptRegion->iHeigh - iFontSize)/2 + iFontSize + ptRegion->iLeftUpY;

	/* 逐个绘制 */
	while (name[i])
	{
		/* get bitmap */
		tFontBitMap.iCurOriginX = iOriginX;
		tFontBitMap.iCurOriginY = iOriginY;
		error = GetFontBitMap(name[i], &tFontBitMap);//获得点阵
		if (error)
		{
			printf("SelectAndInitFont err\n");
			return;
		}
		/* draw on buffer */		
		DrawFontBitMap(&tFontBitMap, dwColor);		

		iOriginX = tFontBitMap.iNextOriginX;
		iOriginY = tFontBitMap.iNextOriginY;	
		i++;
	}
	
}

//4、绘制像素的函数----以前用过课程的09_show_chinese
int PutPixel(int x, int y, unsigned int dwColor)  //dwColor:d-double两倍,w-word,指双字4个字节。
{
	//wz-0830这里pen_8的赋值是啥，忘了！！
    unsigned char *pen_8 = (unsigned char *)(g_tDispBuff.buff+y*line_width+x*pixel_width);
	unsigned short *pen_16;	
	unsigned int *pen_32;	

	unsigned int red, green, blue;	

	pen_16 = (unsigned short *)pen_8;
	pen_32 = (unsigned int *)pen_8;

	//默认用RGB888，对应case 8。case 16是转换的过程。
	switch (g_tDispBuff.iBpp)
	{
		case 8:
		{
			*pen_8 = dwColor;//将8位的颜色值写入Framebuffer
			break;
		}
		case 16:
		{
			/* 565 */
			red   = (dwColor >> 16) & 0xff;
			green = (dwColor >> 8) & 0xff;
			blue  = (dwColor >> 0) & 0xff;
			dwColor = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*pen_16 = dwColor;
			break;
		}
		case 32:
		{
			*pen_32 = dwColor;
			break;
		}
		default:
		{
			printf("can't surport %dbpp\n", g_tDispBuff.iBpp);
			return -1;
			break;
		}
	}
	return 0;
}
//1、命名：ptDispOpr:p指指针，t指结构体。
void RegisterDisplay(PDispOpr ptDispOpr)  //将两个模块所构造的结构体，通过该函数放入链表里面。
{
    ptDispOpr->ptNext = g_DispDevs; //链表头
    g_DispDevs = ptDispOpr;//给链表头赋指向
}

//3、选择函数
int SelectDefaultDisplay(char *name)
{
    PDispOpr pTmp = g_DispDevs;//定义的临时指针
    while(pTmp)
    {
        if (strcmp(name, pTmp->name) ==0) //找一样的
        {
            g_DispDefault = pTmp;//找到了
            return 0;
        }
        pTmp = pTmp->ptNext;//当前的不对，指向下一个
    }
    return -1;//一直没找到，失败。
}
//5、选择默认的display后，去初始化
int InitDefaultDisplay(void)
{
    int ret;
	
	ret = g_DispDefault->DeviceInit();//函数调用
	if (ret)
	{
		printf("DeviceInit err\n");
		return -1;
	}

	ret = g_DispDefault->GetBuffer(&g_tDispBuff);
	if (ret)
	{
		printf("GetBuffer err\n");
		return -1;
	}
    //每一行占多少个字节:多少像素*每像素占多少字节。位初8为字节
	line_width  = g_tDispBuff.iXres * g_tDispBuff.iBpp/8;
	//每个像素的宽度
    pixel_width = g_tDispBuff.iBpp/8;

	return 0;
}

//7、把g_tDispBuff结构体返回上层代码
PDispBuff GetDisplayBuffer(void)
{
	return &g_tDispBuff;
}

//6、上层代码调用5，绘制好了像素，实现刷到硬件上
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{
	return g_DispDefault->FlushRegion(ptRegion, ptDispBuff);
}

//2、用来调用FramebufferInit这个函数
void DisplaySystemRegister(void)
{
	extern void FramebufferRegist(void);  //声明函数
    FramebufferRegist();
}

